package cate.game.play.proce.move;


import cate.common.table.d.GDPlay;
import cate.common.util.XT;
import cate.game.play.config.AllPlayCfg;
import cate.game.play.fighter.Fighter;
import cate.game.play.fighter.FighterPerformance;
import cate.game.play.part.TeamVS;
import cate.game.play.proce.action.ctx.SkillActionCtx;
import cate.game.play.proce.action.ctx.TimeActionCtx;
import cate.game.play.proce.round.RoundCtx;
import cate.game.play.proce.stat.MoveStat;
import cate.game.play.proce.turn.TurnCtx;
import cate.game.play.skill.Skill;
import cate.game.play.skill.SkillSelector;
import cate.game.play.skill.brother.BrotherHandler;
import com.fasterxml.jackson.annotation.JsonIgnore;
import easy.java.dev.note.NoteClass;
import easy.java.dev.note.NoteField;
import lombok.Data;

import java.util.ArrayList;
import java.util.List;


@NoteClass(value = "行动Ctx",detail = "英雄、召唤物、法宝等的行动")
@Data
public class MoveCtx {

    @NoteField(value = "出手轮次ctx")
    public TurnCtx turn;

    @NoteField("行动者")
    public Fighter actor;

    @NoteField(value = "本次释放的技能",detail = "主技能")
    public Skill skill;

    @NoteField("战斗数据统计")
    public MoveStat stat;

    @NoteField("move临时参数")
    public MoveParam param = new MoveParam();

    @NoteField("是否是追加的出手")
    private boolean append;


    public MoveCtx(TurnCtx turn, Fighter actor,Skill skill,boolean append) {
        this.turn = turn;
        this.actor = actor;
        this.skill = skill;
        this.stat = new MoveStat(turn.getStat());
        this.append = append;
    }

    public boolean isAppend(){
        return append;
    }


    /** 开始结算 */
    public void start() {
        if (skill == null) {
            //没有指派技能那就根据cd选一个
            skill = SkillSelector.select(getRound(), actor);
        } else {
            //提前指派了技能 同时不是追加技能 需要走一下技能cd
            if (!isAppend()) {
                SkillSelector.handleSkillCD(getRound(), actor);
            }
        }
        //技能临时替换
        skill = SkillSelector.handleTempReplace(getRound(), actor, skill);

        if (skill != null) {
            actor.beforeOwnerMove(this);
            if (actor.allowUseSkill(skill)) {
                settleSkill(null, null, skill);
                getRound().buildBackAction(actor.getPid());
                actor.onOwnerMoveDone(this);
                getTeamVS().onMoveDone(this);
                stat.move = true;
                FighterPerformance.recSkillCast(getRound().index, actor, skill.cfg.row.protoId);
            }
            skill.reset();
        }
        actor.onOwnerMoveOver();
    }


    /**
     * 结算单个技能
     * @param parent 父action
     * @param brotherTargets 哥哥技能的目标
     * @param skr
     */
    private void settleSkill(SkillActionCtx parent, List<Fighter> brotherTargets, Skill skr) {
        // 技能释放者死亡 或者技能为null 那就结束了
        Fighter actor = this.getActor();
        if (actor.isDead() || skr == null) {
            return;
        }
        List<Fighter> targets;
        //继承的目标（优先继承父技能中的目标 如果没有就继承哥哥技能中的目标）
        List<Fighter> extendTargets;
        if (parent != null) {
            extendTargets = parent.getTargets();
        } else {
            extendTargets = brotherTargets;
        }
        //选择技能目标
        targets = skr.selectTargets(this, extendTargets);
        if (targets == null) {
            targets = new ArrayList<>();
        }
        settleWithTarget(parent, skr, targets);
    }

    /**
     * 选完目标后结算技能
     * @param parent
     * @param skr
     * @param targets
     */
    private void settleWithTarget(SkillActionCtx parent, Skill skr, List<Fighter> targets) {
        //本次行动的action
        SkillActionCtx action = new SkillActionCtx(this, GDPlay.ActionType.SKILL_ACTIVE, actor.getPid(), skr, targets);
        //如果没有父节点 直接在move中添加
        if (parent == null) {
            if (skr.cfg.row.actionTime > 0) {
                action.getPo().playTime = skr.cfg.row.actionTime;
            }
            this.addAction(action);
        } else {
            action.parent = parent;
            parent.addChild(action);
        }
        action.settle();
        if (actor.isAlive()) {
            handleChildren(skr, action);
            handleBrother(skr, action);
        }
    }


    /**
     * 结算子技能
     * @param skr
     * @param parent
     */
    private void handleChildren(Skill skr, SkillActionCtx parent) {
        for (Integer skillId : skr.cfg.getSubSkills()) {
            Skill subSkill = parent.getCfg().skill.buildById(parent.getActor(), skillId);
            settleSkill(parent, null, subSkill);
        }
    }

    /**
     * 结算兄弟技能
     * @param skr
     * @param parent
     */
    private void handleBrother(Skill skr, SkillActionCtx parent) {
        List<Integer> brotherSkills = BrotherHandler.select(skr.cfg.row.brotherMode, skr.cfg.row.brotherCode, parent);
        brotherSkills = XT.mergeNew(brotherSkills, param.getExBrotherSkills(skr.tid));
        if (XT.isBlank(brotherSkills)) {
            return;
        }
        for (Integer skillId : brotherSkills) {
            Skill brotherSkill = parent.getCfg().skill.buildById(parent.getActor(), skillId);
            settleSkill(parent.parent, parent.getTargets(), brotherSkill);
        }
    }

    /** 添加一次行动 */
    public void addAction(SkillActionCtx action) {
        this.getRound().addAction(action);
    }

    /**
     * 构建时间action
     * @return
     */
    public TimeActionCtx buildTimeAction(){
       return getRound().buildTimeAction();
    }

    @JsonIgnore
    public RoundCtx getRound(){
        return turn.getRound();
    }

    @JsonIgnore
    public Fighter getActor(){
        return actor;
    }

    @JsonIgnore
    public AllPlayCfg getCfg(){return getRound().getCfg();}

    @JsonIgnore
    public TeamVS getTeamVS(){return getRound().getTeamVs();}
}
